/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.registration.gui.security;

import it.polimi.registration.business.security.boundary.EventManager;
import it.polimi.registration.business.security.boundary.ForecastManager;
import it.polimi.registration.business.security.entity.Event;
import it.polimi.registration.business.security.entity.MyForecast;
import it.polimi.registration.business.security.weather.OwmClient;
import it.polimi.registration.business.security.weather.WeatherData;
import it.polimi.registration.business.security.weather.WeatherData.WeatherCondition;
import it.polimi.registration.business.security.weather.WeatherStatusResponse;
import static it.polimi.registration.gui.security.ForecastBean.upToDate;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.aksingh.java.api.owm.DailyForecastData;
import net.aksingh.java.api.owm.DailyForecastData.Forecast;
import net.aksingh.java.api.owm.OpenWeatherMap;
import org.json.JSONException;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import net.aksingh.java.api.owm.DailyForecastData.Forecast.Weather;

@Named
@SessionScoped
public class ForecastBean implements Serializable{

    @EJB
    private EventManager evm;
    @EJB
    private ForecastManager fm;

    private MyForecast myforecast;

    List<Event> eventToCheck = new ArrayList<>();
    List<MyForecast> myforecastlist = new ArrayList<>();
    
    @PostConstruct
    public void init(){
    myforecast=new MyForecast();
    eventToCheck = new ArrayList<>();
    myforecastlist = new ArrayList<>();
    }
    
    
    public static Byte upToDate(Date date) {
        ZoneId zone = ZoneId.of("Europe/London");
        LocalDate now = LocalDate.now(zone);
        java.sql.Date sqlDate = new java.sql.Date(date.getTime());
        LocalDate eventDate = sqlDate.toLocalDate();

        Period period = now.until(eventDate);
        byte days = (byte) (period.getDays() + 1);

        return (byte) days;
    }
    
 public void checkEventWeather() {
        String place;
        byte forecastDays;
        DailyForecastData.Forecast w = new DailyForecastData.Forecast();
        myforecastlist = fm.getAllForecast();
        eventToCheck = evm.getEventWithPreference();
        Boolean isNew;
        for (int i = 0; i < eventToCheck.size(); i++) {
            place = eventToCheck.get(i).getLocation().getCity();
            isNew = newForecast(eventToCheck.get(i), myforecastlist);
            forecastDays = upToDate(eventToCheck.get(i).getEndDate());
            w = getForecastForAnEvent(place, forecastDays);
            if (isNew) {
                
                if (!w.getWeather_List().isEmpty()) {
                    myforecast = getMyForecast();
                    myforecast.setDescription(w.getWeather_List().get(0).getWeatherDescription());
                    myforecast.setDate(eventToCheck.get(i).getEndDate());
                    myforecast.setLocation(eventToCheck.get(i).getLocation());
                    fm.save(myforecast);
                    eventToCheck.get(i).setMyforecast(myforecast);
                } else {
                    myforecast = getMyForecast();
                    myforecast.setDescription("Weather not aviable");
                    myforecast.setDate(eventToCheck.get(i).getEndDate());
                    myforecast.setLocation(eventToCheck.get(i).getLocation());
                    fm.save(myforecast);
                    eventToCheck.get(i).setMyforecast(myforecast);
                }
            } else {
                if (!w.getWeather_List().isEmpty()) {
                    myforecast = getMyForecast();
                    myforecast.setDescription(w.getWeather_List().get(0).getWeatherDescription());
                    myforecast.setDate(eventToCheck.get(i).getEndDate());
                    myforecast.setLocation(eventToCheck.get(i).getLocation());
                    fm.updateForecast(eventToCheck.get(i), myforecast.getDescription());
                    eventToCheck.get(i).setMyforecast(myforecast);
            }}

        }

    }

    public void checkOneEventWeather(Event event) {
        String place;
        byte forecastDays;
        
        DailyForecastData.Forecast w = new DailyForecastData.Forecast();
        place = event.getLocation().getCity();
        forecastDays = upToDate(event.getEndDate());
        w = getForecastForAnEvent(place, forecastDays);
        MyForecast forecastOfEvent = new MyForecast();
        forecastOfEvent.setDescription(w.getWeather_List().get(0).getWeatherDescription());
        forecastOfEvent.setDate(event.getEndDate());
        forecastOfEvent.setLocation(event.getLocation());
        fm.save(forecastOfEvent);
    }

    public DailyForecastData.Forecast getForecastForAnEvent(String place, byte forecastDays) {

        try {
            OpenWeatherMap owm = new OpenWeatherMap(OpenWeatherMap.OWM_URL.PARAMETER_UNITS_VALUE_METRIC, "");

            DailyForecastData dfd = owm.dailyForecastByCityName(place, forecastDays);
            if (dfd.getForecast_List() != null) {
                DailyForecastData.Forecast forecast = dfd.getForecast_List().get(0);
                System.out.println(forecast.getWeather_List().get(0).getWeatherName());
                return forecast;
            } else {
                return new DailyForecastData.Forecast();
            }
        } catch (IOException ex) {
            //Logger.getLogger(ForecastBean.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Forecast not aviable");
            return new DailyForecastData.Forecast();
        } catch (org.json.JSONException ex) {
            Logger.getLogger(ForecastBean.class.getName()).log(Level.SEVERE, null, ex);
            return new DailyForecastData.Forecast();
        }
    }

    public Boolean newForecast(Event e, List<MyForecast> f) {
        Boolean b = true;
        for (MyForecast f1 : f) {
            if (giornoUguale(f1.getDate(), e.getEndDate()) && f1.getLocation().getCity().equals(e.getLocation().getCity())) {
                b = false;
            }
        }
        return b;
    }

    /**
     * @param forecast the forecast to set
     */
    public void setMyForecast(MyForecast myforecast) {
        this.myforecast = myforecast;
    }
    
    public MyForecast getMyForecast() {
        if (myforecast == null) {
            myforecast = new MyForecast();
        }

        return myforecast;
    }
    
    public Boolean giornoUguale(Date d1, Date d2) {

        if (d1.getDate() == d2.getDay() && d1.getMonth() == d2.getMonth() && d1.getYear() == d2.getYear()) {
            return true;
        } else {
            return false;
        }
    }
      
}

